<?php

namespace App;

use App\ApiException;

class Application
{
    static private $class;
    static private $controller;
    static private $param;
    static private $error;
    function __construct()
    {
        //register_shutdown_function 函数必须在所有的程序执行之间注册捕获程序终止的错误
        register_shutdown_function([static::class, 'register']);
        self::httparse();
    }
    //解析http请求的url信息
    static function httparse()
    {
        //获取浏览器中的路径
        $path_info = explode('/', substr($_SERVER['PATH_INFO'], 1));
        //var_dump($path_info);
        if (count($path_info) >= 2) {
            self::$class = $path_info[0]; //类
            self::$controller = $path_info[1]; //方法
        }
        //echo $_SERVER['REQUEST_METHOD'];
        //获取传递参数
        switch ($_SERVER['REQUEST_METHOD']) {
            case "POST":
                //当Action存在而类别为空时，创建默认的类和控制器
                if (isset($_POST['Action'])) {
                    self::$class = 'lightrim';
                    self::$controller = $_POST['Action'];
                    unset($_POST['Action']);
                }
                self::$param = $_POST;
                break;
            case "GET":
                if (isset($_GET['Action'])) {
                    self::$class = 'lightrim';
                    self::$controller = $_GET['Action'];
                    unset($_POST['Action']);
                }
                self::$param = $_GET;
                break;
        }
    }

    //运行
    static function run()
    {
        //var_dump("类名：".self::$class, "控制器：".self::$controller);
        //获取控制器中的类  ucfirst首字母转为大写
        $class = "\App\controller\\" . ucfirst(self::$class);
        try {
            if (class_exists($class) && self::$controller) {
                //调用对象中指定的方法，并传参数
                $result = call_user_func([new $class, self::$controller], self::$param);
                //var_dump($result);
                //返回值必须是字符串
                if (is_string($result)) {
                    echo $result;
                } else {
                    throw new ApiException('返回错误格式格式');
                }
            } else {
                //控制器或类错误直接调整默认页面
                $result = call_user_func([new \App\controller\Index, 'index']);
                echo $result;
            }
            // echo 'run';
        } catch (\Throwable $e) {
            //判断异常是否API异常
            if ($e instanceof ApiException) {
                echo Json([], $e->getCode(), $e->getMessage());
            }
            //其他错误和异常存日志文件
            var_dump($e);
            Logs($e);
        }
    }
    /**
     * 注册错误回调
     */
    static function register()
    {
        $error = error_get_last();
        if ($error) {
            // $message = '文件 : ' . $error['file'] . PHP_EOL;
            // $message .= '行数 : ' . $error['line'] . PHP_EOL;
            // $message .= '错误 : ' . $error['message'] . PHP_EOL;
            // $message .= '类型 : ' . $error['type'] . PHP_EOL;
            try {
                throw new \Exception($error['message'], $error['line']);
            } catch (\Throwable $e) {
                Logs($e);
            }
        }
    }

    //错误异常(已废弃)
    static function error()
    {
        register_shutdown_function("fatal_handler");
        set_error_handler("error_handler");
        define('E_FATAL',  E_ERROR | E_USER_ERROR |  E_CORE_ERROR | E_COMPILE_ERROR | E_RECOVERABLE_ERROR | E_PARSE);

        //获取fatal error
        function fatal_handler()
        {
            $error = error_get_last();
            if ($error && ($error["type"] === ($error["type"] & E_FATAL))) {
                $errno   = $error["type"];
                $errfile = $error["file"];
                $errline = $error["line"];
                $errstr  = $error["message"];
                error_handler($errno, $errstr, $errfile, $errline);
            }
        }
        //获取所有的error
        function error_handler($errno, $errstr, $errfile, $errline)
        {
            $str = <<<EOF
         "errno":$errno
         "errstr":$errstr
         "errfile":$errfile
         "errline":$errline
EOF;
            //获取到错误可以自己处理，比如记Log、报警等等
            //echo $str;
            throw new \Exception($str);
        }
    }
}
